import "./Role.scss";
import React, { Component, Fragment } from "react";
import { DownOutlined } from "@ant-design/icons";
import { Tree, Button, Form, Input, Modal, Select, message, Popconfirm, Transfer } from "antd";
import { PlusOutlined, DeleteOutlined, CloudSyncOutlined } from "@ant-design/icons";
import {
    getRoles,
    updateRole,
    deleteRole,
    addRole,
    getMenusInRole,
    addRefMenu,
    deleteRefMenu,
    getInterfacesInRole,
    addRefInterface,
    deleteRefInterface,
} from "@/api/role";
import { normalGetAllMenu } from "@/api/menu";
import CustomModal from "@/components/common/CustomModal";
const { Option } = Select;
export default class Role extends Component {
    constructor() {
        super();
        this.state = {
            treeData: [],
            isAddRole: true,
            roleModalVisible: false,
            menuModalVisible: false,
            interfaceModalVisible: false,
            copyOtherInterfaceVisible: false,
            editRoleId: null,
            editRoleName: null,
            editRoleDescription: null,
            editMenuId: null,
            editInterfaceIndex: null,
            menuTreeData: [],
            interfaceTreeData: [],
            allMenu: [],
            othersInterfaces: [],
            targetInterfaceskey: [],
            allRolesInterfaces: [],
        };
    }
    UNSAFE_componentWillMount() {
        this.getRoles_com();
    }
    onSelect = (selectedKeys, info) => {
        if (selectedKeys.length) {
            this.setState(
                {
                    editRoleName: info.node.name,
                    editRoleDescription: info.node.description,
                    editRoleId: selectedKeys[0],
                },
                () => {
                    this.getInterfaces_com();
                    this.getMenusInRole_com();
                }
            );
        } else {
            this.setState({
                editRoleName: null,
                editRoleDescription: null,
                editRoleId: null,
            });
        }
    };
    selectMenu = (selectedKeys, info) => {
        this.setState({
            editMenuId: selectedKeys[0],
        });
    };
    selectInterface = (selectedKeys, info) => {
        this.setState({
            editInterfaceIndex: selectedKeys[0],
        });
    };
    getMenusInRole_com = () => {
        const { editRoleId } = this.state;
        getMenusInRole({ _id: editRoleId }).then(res => {
            if (res.code === 200) {
                this.setState({
                    menuTreeData: res.data.map((item, key) => ({ ...item, key: item._id })),
                });
            }
        });
    };
    getInterfaces_com = () => {
        const { editRoleId } = this.state;
        getInterfacesInRole({ _id: editRoleId }).then(res => {
            if (res.code === 200) {
                this.setState({
                    interfaceTreeData: res.data.map((item, key) => ({ ...item, title: item.name, key })),
                });
            }
        });
    };
    getRoles_com = () => {
        getRoles().then(res => {
            if (res.code === 200) {
                this.setState(
                    {
                        treeData: res.data.map(item => ({ ...item, title: item.name, key: item._id })),
                    },
                    () => {
                        this.setState({
                            allRolesInterfaces: this.state.treeData
                                .map(item => item.interfaces)
                                .reduce((pre, item) => pre.concat(item))
                                .map(item => ({ ...item, key: item.interface })),
                        });
                    }
                );
            }
        });
    };
    changeTransfer = (nextTargetKeys, direction, moveKeys) => {
        this.setState({ targetInterfaceskey: nextTargetKeys });
    };
    render() {
        const {
            treeData,
            roleModalVisible,
            isAddRole,
            editRoleId,
            editRoleName,
            editRoleDescription,
            menuTreeData,
            menuModalVisible,
            allMenu,
            editMenuId,
            interfaceModalVisible,
            interfaceTreeData,
            editInterfaceIndex,
            copyOtherInterfaceVisible,
            targetInterfaceskey,
            allRolesInterfaces,
        } = this.state;
        return (
            <div>
                <div className="flex">
                    <div className="mr-20">
                        <div className="mb-10 operation-wrap">
                            <Button
                                onClick={() => {
                                    this.setState({ roleModalVisible: true, isAddRole: true }, () => {
                                        this.refs.roleFormRef.resetFields();
                                    });
                                }}
                                type="primary"
                                size="small"
                            >
                                添加角色
                            </Button>
                            <Button
                                onClick={() => {
                                    if (editRoleId) {
                                        this.setState({ roleModalVisible: true, isAddRole: false }, () => {
                                            this.refs.roleFormRef.setFieldsValue({
                                                name: editRoleName,
                                                description: editRoleDescription,
                                            });
                                        });
                                    } else {
                                        message.warn("请先选择角色");
                                    }
                                }}
                                size="small"
                            >
                                编辑角色
                            </Button>
                            <Popconfirm
                                title={`确定删除${editRoleName ? editRoleName : ""}吗？`}
                                okText="确定"
                                cancelText="取消"
                                onConfirm={() => {
                                    if (editRoleId) {
                                        deleteRole({ _id: editRoleId }).then(res => {
                                            if (res.code === 200) {
                                                this.setState({
                                                    editRoleId: null,
                                                    editRoleName: null,
                                                });
                                                this.getRoles_com();
                                                message.success("删除成功");
                                            }
                                        });
                                    } else {
                                        message.warn("请先选择角色");
                                    }
                                }}
                            >
                                <Button size="small" danger>
                                    删除角色
                                </Button>
                            </Popconfirm>
                        </div>
                        <div className="tree-wrap tree1">
                            <Tree
                                showLine
                                switcherIcon={<DownOutlined />}
                                defaultExpandedKeys={["0-0-0"]}
                                selectable={true}
                                onSelect={this.onSelect}
                                treeData={treeData}
                            ></Tree>
                        </div>
                    </div>
                    <div className="jc-evenly rightTreeArea">
                        {editRoleId ? (
                            <Fragment>
                                <div>
                                    <div className="mb-10 operation-wrap">
                                        <Button
                                            type="primary"
                                            size="small"
                                            onClick={() =>
                                                this.setState({ interfaceModalVisible: true }, () => {
                                                    this.refs.interfacesFormRef.resetFields();
                                                })
                                            }
                                        >
                                            <PlusOutlined />
                                        </Button>
                                        <Button
                                            danger
                                            size="small"
                                            onClick={() => {
                                                if (editInterfaceIndex || editInterfaceIndex === 0) {
                                                    deleteRefInterface({
                                                        roleId: editRoleId,
                                                        interfaceIndex: editInterfaceIndex,
                                                    }).then(res => {
                                                        if (res.code === 200) {
                                                            this.getInterfaces_com();
                                                            message.success("删除成功");
                                                        }
                                                    });
                                                } else {
                                                    message.warn("请先选择接口");
                                                }
                                            }}
                                        >
                                            <DeleteOutlined />
                                        </Button>
                                        <Button
                                            shape="circle"
                                            size="small"
                                            type="primary"
                                            onClick={() =>
                                                this.setState({
                                                    copyOtherInterfaceVisible: true,
                                                    targetInterfaceskey: interfaceTreeData.map(item => item.interface),
                                                })
                                            }
                                        >
                                            <CloudSyncOutlined />
                                        </Button>
                                    </div>
                                    <div className="tree-wrap tree2">
                                        <Tree
                                            showLine
                                            switcherIcon={<DownOutlined />}
                                            treeData={interfaceTreeData}
                                            onSelect={this.selectInterface}
                                        ></Tree>
                                    </div>
                                </div>
                                <div>
                                    <div className="mb-10 operation-wrap">
                                        <Button
                                            type="primary"
                                            onClick={() => {
                                                this.setState({ menuModalVisible: true }, () => {
                                                    normalGetAllMenu().then(res => {
                                                        if (res.code === 200) {
                                                            this.setState(
                                                                {
                                                                    allMenu: res.data,
                                                                },
                                                                () => {
                                                                    this.refs.menuFormRef.setFieldsValue({
                                                                        menuIds: menuTreeData.map(item => item._id),
                                                                    });
                                                                }
                                                            );
                                                        }
                                                    });
                                                });
                                            }}
                                            size="small"
                                        >
                                            <PlusOutlined />
                                        </Button>
                                        <Button
                                            danger
                                            size="small"
                                            onClick={() => {
                                                if (editMenuId) {
                                                    deleteRefMenu({ roleId: editRoleId, menuId: editMenuId }).then(
                                                        res => {
                                                            if (res.code === 200) {
                                                                message.success("删除成功");
                                                                setTimeout(() => {
                                                                    location.reload();
                                                                }, 600);
                                                            }
                                                        }
                                                    );
                                                } else {
                                                    message.warn("请先选择菜单");
                                                }
                                            }}
                                        >
                                            <DeleteOutlined />
                                        </Button>
                                    </div>
                                    <div className="tree-wrap tree3">
                                        <Tree
                                            showLine
                                            switcherIcon={<DownOutlined />}
                                            treeData={menuTreeData}
                                            onSelect={this.selectMenu}
                                        ></Tree>
                                    </div>
                                </div>
                            </Fragment>
                        ) : (
                            "请在左侧选择角色"
                        )}
                    </div>
                </div>
                <CustomModal
                    title="复制权限"
                    visible={copyOtherInterfaceVisible}
                    onCancel={() => this.setState({ copyOtherInterfaceVisible: false })}
                    onOk={() => {
                        addRefInterface({
                            roleId: editRoleId,
                            interface: allRolesInterfaces.filter(item => targetInterfaceskey.includes(item.interface)),
                        }).then(res => {
                            if (res.code === 200) {
                                this.getInterfaces_com();
                                message.success("同步成功");
                                this.setState({ copyOtherInterfaceVisible: false });
                            }
                        });
                    }}
                >
                    {treeData.length ? (
                        <Transfer
                            oneWay
                            titles={["其他", "我的"]}
                            render={item => item.name}
                            onChange={this.changeTransfer}
                            targetKeys={targetInterfaceskey}
                            dataSource={allRolesInterfaces}
                        />
                    ) : (
                        ""
                    )}
                </CustomModal>
                <CustomModal
                    visible={interfaceModalVisible}
                    onCancel={() => {
                        this.setState({ interfaceModalVisible: false });
                    }}
                    onOk={() => {
                        this.refs.interfacesFormRef.validateFields().then(formData => {
                            addRefInterface({ interface: formData, roleId: editRoleId }).then(res => {
                                if (res.code === 200) {
                                    this.getInterfaces_com();
                                    message.success("添加成功");
                                    this.setState({
                                        interfaceModalVisible: false,
                                    });
                                }
                            });
                        });
                    }}
                >
                    <Form ref="interfacesFormRef" wrapperCol={{ span: 12 }} labelCol={{ span: 7 }}>
                        <Form.Item name="name" label="接口名" rules={[{ required: true, message: "接口名不能为空" }]}>
                            <Input />
                        </Form.Item>
                        <Form.Item
                            name="interface"
                            label="接口地址"
                            rules={[{ required: true, message: "接口地址不能为空" }]}
                        >
                            <Input />
                        </Form.Item>
                    </Form>
                </CustomModal>
                <Modal
                    title="添加对应菜单"
                    keyboard={true}
                    visible={menuModalVisible}
                    onOk={() => {
                        this.refs.menuFormRef.validateFields().then(formData => {
                            const { menuIds } = formData;
                            const { editRoleId: roleId } = this.state;
                            addRefMenu({ menuIds, roleId }).then(res => {
                                if (res.code === 200) {
                                    message.success("添加成功");
                                    this.setState({
                                        menuModalVisible: false,
                                    });
                                    setTimeout(() => {
                                        location.reload();
                                    }, 600);
                                }
                            });
                        });
                    }}
                    onCancel={() => {
                        this.setState({ menuModalVisible: false });
                    }}
                    okText="确定"
                    cancelText="取消"
                >
                    <Form ref="menuFormRef" wrapperCol={{ span: 12 }} labelCol={{ span: 7 }}>
                        <Form.Item label="菜单" name="menuIds" rules={[{ required: true, message: "请选择菜单" }]}>
                            <Select mode="multiple">
                                {allMenu.map(item => (
                                    <Option key={item._id}>{item.title}</Option>
                                ))}
                            </Select>
                        </Form.Item>
                    </Form>
                </Modal>
                <Modal
                    title="添加/编辑角色"
                    keyboard={true}
                    visible={roleModalVisible}
                    onOk={() => {
                        this.refs.roleFormRef.validateFields().then(formData => {
                            if (isAddRole) {
                                addRole(formData).then(res => {
                                    if (res.code === 200) {
                                        this.getRoles_com();
                                        this.setState({ roleModalVisible: false });
                                        message.success("添加成功");
                                    }
                                });
                            } else {
                                updateRole(formData).then(res => {
                                    if (res.code === 200) {
                                        this.getRoles_com();
                                        this.setState({ roleModalVisible: false });
                                        message.success("修改成功");
                                    }
                                });
                            }
                        });
                    }}
                    onCancel={() => {
                        this.setState({ roleModalVisible: false });
                    }}
                    okText="确定"
                    cancelText="取消"
                >
                    <Form ref="roleFormRef" wrapperCol={{ span: 12 }} labelCol={{ span: 7 }}>
                        <Form.Item label="角色名" name="name" rules={[{ required: true, message: "请输入角色名" }]}>
                            <Input />
                        </Form.Item>
                        <Form.Item label="描述" name="description">
                            <Input />
                        </Form.Item>
                    </Form>
                </Modal>
            </div>
        );
    }
}
